package com.carleasoft.mps.adu.business.role.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carleasoft.mps.adu.business.role.bean.entity.*;
import com.carleasoft.mps.adu.business.role.bean.po.AuthorityRoleInfoPagePo;
import com.carleasoft.mps.adu.business.role.bean.po.AuthorityRoleInfoPo;
import com.carleasoft.mps.adu.business.role.bean.po.RoleParamsPo;
import com.carleasoft.mps.adu.business.role.bean.vo.*;
import com.carleasoft.mps.adu.business.role.dao.*;
import com.carleasoft.mps.adu.business.role.service.AuthorityRoleService;
import com.carleasoft.mps.core.user.Constants;
import com.carleasoft.mps.adu.common.pops.ShiroMenuConfig;
import com.carleasoft.mps.core.exceptions.BusinessException;
import com.carleasoft.mps.core.perm.DataPermCache;
import com.carleasoft.mps.core.perm.ThreadPermDataContext;
import com.carleasoft.mps.core.user.ThreadUserContext;
import com.carleasoft.mps.core.user.UserCacheData;
import com.carleasoft.mps.core.utils.DateUtil;
import com.google.common.base.Joiner;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.carleasoft.mps.adu.common.constants.BusinessErrorEnum.*;

/**
 * <p>Description: role serviceImpl</p>
 *
 * @author ztm
 * @since 2020-05-11
 */
@Service
public class AuthorityRoleServiceImpl extends ServiceImpl<AuthorityRoleDao, AuthorityRoleEntity> implements AuthorityRoleService {

    @Autowired
    AuthorityRolePermissionDao authorityRolePermissionDao;
    @Autowired
    AuthorityDataPermsDao authorityDataPermsDao;
    @Autowired
    AuthorityUserDataDao authorityUserDataDao;
    @Autowired
    AuthorityTargetRoleDao authorityTargetRoleDao;
    @Autowired
    ShiroMenuConfig shiroMenuConfig;


    /**
     * 给目标对象反向添加权限
     *
     * @param
     * @return void
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void revGrantRole(String userCode, String userName, String type) {
        AuthorityTargetRoleEntity authorityTargetRoleEntity = authorityTargetRoleDao.selectOne(new QueryWrapper<AuthorityTargetRoleEntity>().eq("TARGET_CODE", userCode));

        if (authorityTargetRoleEntity == null) {
            //走新增
            AuthorityRoleInfoPo authorityRoleInfoPo = new AuthorityRoleInfoPo();
            authorityRoleInfoPo.setTargetName(userName);
            authorityRoleInfoPo.setTargetCode(userCode);
            authorityRoleInfoPo.setAppResources(shiroMenuConfig.getMenu().get(type));
            authorityRoleInfoPo.setTargetType(Constants.TARGET_USER);
            this.addRole(authorityRoleInfoPo);
        } else {
            AuthorityRoleEntity roleEntity = this.getBaseMapper().selectOne(new QueryWrapper<AuthorityRoleEntity>().eq("ROLE_CODE", authorityTargetRoleEntity.getRoleCode()));
            //组装RolePermission对象
            List<AuthorityRolePermissionEntity> authorityRolePermissionEntities = new ArrayList<>();
            for (String resource : shiroMenuConfig.getMenu().get(type)) {
                //重复添加，删除的时候解除其中一条，不影响其他
                AuthorityRolePermissionEntity authorityRolePermissionEntity = new AuthorityRolePermissionEntity();
                authorityRolePermissionEntity.setRoleCode(roleEntity.getRoleCode());
                authorityRolePermissionEntity.setPermissionCode(resource);
                authorityRolePermissionEntities.add(authorityRolePermissionEntity);
            }
            if (CollectionUtil.isNotEmpty(authorityRolePermissionEntities)) {
                authorityRolePermissionDao.batchAddRolePermission(authorityRolePermissionEntities);
            }

        }
    }

    /**
     * 给目标对象解除反向添加权限
     *
     * @param
     * @return void
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void delGrantRole(String userCode, String userName, String type) {
        AuthorityTargetRoleEntity authorityTargetRoleEntity = authorityTargetRoleDao.selectOne(new QueryWrapper<AuthorityTargetRoleEntity>().eq("TARGET_CODE", userCode));

        if (authorityTargetRoleEntity != null) {

            AuthorityRoleEntity roleEntity = this.getBaseMapper().selectOne(new QueryWrapper<AuthorityRoleEntity>().eq("ROLE_CODE", authorityTargetRoleEntity.getRoleCode()));
            //组装RolePermission对象
            if (roleEntity != null) {
                List<AuthorityRolePermissionEntity> authorityRolePermissionEntities = new ArrayList<>();
                for (String resource : shiroMenuConfig.getMenu().get(type)) {
                    List<AuthorityRolePermissionEntity> ares = authorityRolePermissionDao.selectList(new QueryWrapper<AuthorityRolePermissionEntity>()
                            .eq("ROLE_CODE", roleEntity.getRoleCode())
                            .eq("PERMISSION_CODE", resource));
                    if (ares != null && ares.size() > 0) {
                        authorityRolePermissionDao.deleteById(ares.get(0).getId());
                    }
                }
            }
        }
    }

    /**
     * 给目标对象设置权限
     *
     * @param authorityRoleInfoPo
     * @return void
     */
    @Override
    public void addOrUpdataRole(AuthorityRoleInfoPo authorityRoleInfoPo) {
        if (StringUtils.isEmpty(authorityRoleInfoPo.getRoleCode())) {
            this.addRole(authorityRoleInfoPo);
        } else {
            this.updateRole(authorityRoleInfoPo);
        }
    }

    /**
     * 添加权限
     *
     * @param authorityRoleInfoPo
     * @return void
     */
    @Transactional(rollbackFor = {Exception.class})
    public void addRole(AuthorityRoleInfoPo authorityRoleInfoPo) {

        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        //校验角色名称是否重复
        int roleNameCount = this.getBaseMapper().selectRoleCountByRoleName(authorityRoleInfoPo);
        if (roleNameCount > 0) {
            //角色名称重复
            throw new BusinessException(DUPLICATE_ROLE_NAME);
        }
        //生成角色编码
        AuthorityRoleEntity authorityRoleEntity = new AuthorityRoleEntity();
        authorityRoleEntity.setRoleCode(IdWorker.getIdStr());
        /**********新增角色基本信息************/

        authorityRoleEntity.setRoleType(authorityRoleInfoPo.getTargetType());
        authorityRoleEntity.setOrganizationCode(user.getOrgCodeJoin());
        authorityRoleEntity.setDeptCode(user.getDeptCodeJoin());
        //权限赋予规则，请勿随便改动，ztm

        authorityRoleEntity.setRoleName(authorityRoleInfoPo.getTargetName());
        this.getBaseMapper().addRole(authorityRoleEntity);
        /**********新增角色菜单关联关系信息************/
        //组装RolePermission对象
        List<String> res = new ArrayList<>();
        res.addAll(authorityRoleInfoPo.getAppResources());
        res.addAll(authorityRoleInfoPo.getWebResources() == null ? new ArrayList<>() : authorityRoleInfoPo.getWebResources());
        for (String resource : res) {
            AuthorityRolePermissionEntity authorityRolePermissionEntity = new AuthorityRolePermissionEntity();
            authorityRolePermissionEntity.setRoleCode(authorityRoleEntity.getRoleCode());
            authorityRolePermissionEntity.setPermissionCode(resource);
            authorityRolePermissionDao.insert(authorityRolePermissionEntity);
        }
        /**********新增角色数据权限************/

        if (authorityRoleInfoPo.getDataType() == Constants.DATA_ALL || authorityRoleInfoPo.getDataType() == Constants.DATA_OWNER_ORGANIZATION || authorityRoleInfoPo.getDataType() == Constants.DATA_OWNER_DEPT) {
            AuthorityUserDataEntity authorityUserDataEntity = new AuthorityUserDataEntity();
            authorityUserDataEntity.setDataType(authorityRoleInfoPo.getDataType());
            authorityUserDataEntity.setDataCode(IdWorker.getIdStr());
            authorityUserDataEntity.setRoleCode(authorityRoleEntity.getRoleCode());
            authorityUserDataDao.insert(authorityUserDataEntity);
        } else {
            if (authorityRoleInfoPo.getPermCodes() != null && authorityRoleInfoPo.getPermCodes().size() > 0) {
                AuthorityUserDataEntity authorityUserDataEntity = new AuthorityUserDataEntity();
                authorityUserDataEntity.setDataType(authorityRoleInfoPo.getDataType());
                authorityUserDataEntity.setDataCode(IdWorker.getIdStr());
                authorityUserDataEntity.setRoleCode(authorityRoleEntity.getRoleCode());
                authorityUserDataDao.insert(authorityUserDataEntity);
                for (String perCodes : authorityRoleInfoPo.getPermCodes()) {
                    AuthorityDataPermsEntity authorityDataPermsEntity = new AuthorityDataPermsEntity();
                    authorityDataPermsEntity.setDataCode(authorityUserDataEntity.getDataCode());
                    authorityDataPermsEntity.setPermCodes(perCodes);
                    authorityDataPermsDao.insert(authorityDataPermsEntity);
                }

            }
        }

        //组装AuthorityDataPermsEntity对象
        //新增关系表
        AuthorityTargetRoleEntity authorityTargetRoleEntity = new AuthorityTargetRoleEntity();
        authorityTargetRoleEntity.setTargetCode(authorityRoleInfoPo.getTargetCode());
        authorityTargetRoleEntity.setTargetType(authorityRoleInfoPo.getTargetType());
        authorityTargetRoleEntity.setRoleCode(authorityRoleEntity.getRoleCode());
        authorityTargetRoleDao.insert(authorityTargetRoleEntity);

    }

    /**
     * 修改角色
     *
     * @param authorityRoleInfoPo
     * @return void
     */
    @Transactional(rollbackFor = {Exception.class})
    public void updateRole(AuthorityRoleInfoPo authorityRoleInfoPo) {

        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        authorityRoleInfoPo.setUpdatePersonCode(user.getUserCode());
        authorityRoleInfoPo.setUpdatePersonName(user.getUserName());
        authorityRoleInfoPo.setUpdateTime(DateUtil.getCurrentTimeStr());

        AuthorityRoleEntity roleEntity = this.getBaseMapper().selectOne(new QueryWrapper<AuthorityRoleEntity>().eq("ROLE_CODE", authorityRoleInfoPo.getRoleCode()));
        if (roleEntity == null) {
            //找不到记录
            throw new BusinessException(RECORD_DOES_NOT_EXIST);
        }
        /**********编辑角色菜单关联关系************/
        //先删除原有的关联关系
        authorityRolePermissionDao.deleteRolePermission(authorityRoleInfoPo.getRoleCode());
        //新增现有的关联关系
        List<String> res = new ArrayList<>();
        res.addAll(authorityRoleInfoPo.getAppResources());
        res.addAll(authorityRoleInfoPo.getWebResources());
        for (String resource : res) {
            AuthorityRolePermissionEntity authorityRolePermissionEntity = new AuthorityRolePermissionEntity();
            authorityRolePermissionEntity.setRoleCode(roleEntity.getRoleCode());
            authorityRolePermissionEntity.setPermissionCode(resource);
            authorityRolePermissionDao.insert(authorityRolePermissionEntity);
        }

        /**********更新角色数据权限************/


        //删除原有数据
        authorityDataPermsDao.deleteDataPermissions(authorityRoleInfoPo.getRoleCode());
        authorityUserDataDao.deleteUserDataRole(authorityRoleInfoPo.getRoleCode());

        if (authorityRoleInfoPo.getDataType() == Constants.DATA_ALL || authorityRoleInfoPo.getDataType() == Constants.DATA_OWNER_ORGANIZATION || authorityRoleInfoPo.getDataType() == Constants.DATA_OWNER_DEPT) {
            AuthorityUserDataEntity authorityUserDataEntity = new AuthorityUserDataEntity();
            authorityUserDataEntity.setDataType(authorityRoleInfoPo.getDataType());
            authorityUserDataEntity.setDataCode(IdWorker.getIdStr());
            authorityUserDataEntity.setRoleCode(roleEntity.getRoleCode());
            authorityUserDataDao.insert(authorityUserDataEntity);
        } else {
            if (authorityRoleInfoPo.getPermCodes() != null && authorityRoleInfoPo.getPermCodes().size() > 0) {
                AuthorityUserDataEntity authorityUserDataEntity = new AuthorityUserDataEntity();
                authorityUserDataEntity.setDataType(authorityRoleInfoPo.getDataType());
                authorityUserDataEntity.setDataCode(IdWorker.getIdStr());
                authorityUserDataEntity.setRoleCode(roleEntity.getRoleCode());
                authorityUserDataDao.insert(authorityUserDataEntity);
                for (String perCodes : authorityRoleInfoPo.getPermCodes()) {
                    AuthorityDataPermsEntity authorityDataPermsEntity = new AuthorityDataPermsEntity();
                    authorityDataPermsEntity.setDataCode(authorityUserDataEntity.getDataCode());
                    authorityDataPermsEntity.setPermCodes(perCodes);
                    authorityDataPermsDao.insert(authorityDataPermsEntity);
                }
            }
        }
    }

    /**
     * 删除权限
     *
     * @param roleParamsPo
     * @return void
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void deleteRole(RoleParamsPo roleParamsPo) {
        if (StringUtils.isEmpty(roleParamsPo.getRoleCode())) {
            AuthorityTargetRoleEntity authorityTargetRoleEntity = this.authorityTargetRoleDao.selectOne(Wrappers.<AuthorityTargetRoleEntity>lambdaQuery().eq(AuthorityTargetRoleEntity::getTargetCode, roleParamsPo.getTargetCode()));
            if (Objects.nonNull(authorityTargetRoleEntity)) {
                roleParamsPo.setRoleCode(authorityTargetRoleEntity.getRoleCode());
            } else {
                return;
            }
        }
        AuthorityRoleEntity roleEntity = this.getBaseMapper().selectOne(new QueryWrapper<AuthorityRoleEntity>().eq("ROLE_CODE", roleParamsPo.getRoleCode()));
        if (roleEntity == null) {
            //找不到记录,
            throw new BusinessException(RECORD_DOES_NOT_EXIST);
        }
        this.getBaseMapper().deleteRole(roleParamsPo.getRoleCode());
        /****删除角色与菜单数据权限关系*****/
        authorityRolePermissionDao.deleteRolePermission(roleParamsPo.getRoleCode());
        authorityDataPermsDao.deleteDataPermissions(roleParamsPo.getRoleCode());
        authorityUserDataDao.deleteUserDataRole(roleParamsPo.getRoleCode());
        /****删除角色与目标授权对象关系*****/
        authorityTargetRoleDao.deleteTargetRole(roleParamsPo.getRoleCode());
    }

    /**
     * 获取用户角色列表,分页
     *
     * @param page,authorityUserAllInfoVo
     * @return List
     */
    @Override
    public Page<AuthorityRoleInfoPageVo> pageQuery(Page<AuthorityRoleInfoPagePo> page, AuthorityRoleInfoPagePo authorityRoleInfoPagePo) {
        UserCacheData user = ThreadUserContext.getCurrentCacheUser();
        DataPermCache dataPermCache = ThreadPermDataContext.getCurrentDataPermCache();
//        authorityRoleInfoPagePo.setUserCat(user.getUserCat());
        authorityRoleInfoPagePo.setDataCodes(Joiner.on(",").join(dataPermCache.getDeptCodes()));
        authorityRoleInfoPagePo.setDataPermType(dataPermCache.getDataType());
        Page<AuthorityRoleInfoPageVo> authorityRoleInfoPageVos = this.getBaseMapper().pageQuery(page, authorityRoleInfoPagePo);
        return authorityRoleInfoPageVos;
    }
}

